package logger

// 颜色常量
const (
	Reset       = "\033[0m"
	Red         = "\033[31m"
	Green       = "\033[32m"
	Yellow      = "\033[33m"
	Blue        = "\033[34m"
	Magenta     = "\033[35m"
	Cyan        = "\033[36m"
	White       = "\033[37m"
	BlueBold    = "\033[34;1m"
	MagentaBold = "\033[35;1m"
	RedBold     = "\033[31;1m"
	YellowBold  = "\033[33;1m"
)

const (
	// Silent silent log level
	Silent LogLevel = iota + 1
	// Error error log level
	Error
	// Warn warn log level
	Warn
	// Info info log level
	Info
)

// LogLevel 日志级别
type LogLevel int

// Interface 日志统一接口
type Interface interface {
	LogMode(LogLevel) Interface
	Info(string, ...interface{})
	Warn(string, ...interface{})
	Error(string, ...interface{})
}

// Writer 日志输出规范
type Writer interface {
	Printf(string, ...interface{})
}

// Config 日志配置
type Config struct {
	Colorful bool
	LogLevel LogLevel
}

type Logger struct {
	Writer
	Config
	infoStr, warnStr, errStr            string
	traceStr, traceErrStr, traceWarnStr string
}

// New 初始化 Logger
func New(writer Writer, config Config) Interface {
	var (
		infoStr      = "%s [info] "
		warnStr      = "%s [warn] "
		errStr       = "%s [error] "
		traceStr     = "%s [%.3fms] [rows:%v] %s"
		traceWarnStr = "%s %s [%.3fms] [rows:%v] %s"
		traceErrStr  = "%s %s [%.3fms] [rows:%v] %s"
	)

	if config.Colorful {
		infoStr = Green + Reset + Green + "[info] " + Reset
		warnStr = BlueBold + Reset + Magenta + "[warn] " + Reset
		errStr = Magenta + Reset + Red + "[error] " + Reset
	}

	return &Logger{
		Writer:       writer,
		Config:       config,
		infoStr:      infoStr,
		warnStr:      warnStr,
		errStr:       errStr,
		traceStr:     traceStr,
		traceWarnStr: traceWarnStr,
		traceErrStr:  traceErrStr,
	}
}

// -----------------------------------------以下为 Logger 实现-------------------------------------------------

func (log *Logger) LogMode(level LogLevel) Interface {
	newLogger := *log
	newLogger.LogLevel = level
	return &newLogger
}

func (log *Logger) Info(msg string, data ...interface{}) {
	if log.LogLevel >= Info {
		log.Printf(log.infoStr+msg, data...)
	}
}

func (log *Logger) Warn(msg string, data ...interface{}) {
	if log.LogLevel >= Warn {
		log.Printf(log.warnStr+msg, data...)
	}
}

func (log *Logger) Error(msg string, data ...interface{}) {
	if log.LogLevel >= Error {
		log.Printf(log.errStr+msg, data...)
	}
}
